<?php

declare(strict_types=1);
/**
 * This file is part of MoChat.
 * @link     https://mo.chat
 * @document https://mochat.wiki
 * @contact  group@mo.chat
 * @license  https://github.com/mochat-cloud/mochat/blob/master/LICENSE
 */
namespace MoChat\App\User\Action\Dashboard;

use Hyperf\Di\Annotation\Inject;
use Hyperf\HttpServer\Annotation\Controller;
use Hyperf\HttpServer\Annotation\RequestMapping;
use MoChat\App\Tenant\Contract\TenantContract;
use MoChat\App\User\Constants\Status;
use MoChat\App\User\Contract\UserContract;
use MoChat\App\ValidationCode\Service\ValidationCodeService;
use MoChat\Framework\Action\AbstractAction;
use MoChat\Framework\Constants\ErrorCode;
use MoChat\Framework\Exception\CommonException;
use MoChat\Framework\Request\ValidateSceneTrait;
use Qbhy\HyperfAuth\AuthManager;
use Qbhy\SimpleJwt\JWTManager;

/**
 * 验证码登陆验证
 * @Controller
 */
class ValidationCodeAuth extends AbstractAction
{
    use ValidateSceneTrait;

    /**
     * @Inject
     * @var AuthManager
     */
    protected $auth;

    /**
     * @Inject
     * @var UserContract
     */
    protected $user;

    /**
     * @Inject
     * @var TenantContract
     */
    protected $tenantService;

    /**
     * @Inject
     * @var ValidationCodeService
     */
    protected $validationCode;

    /**
     * @RequestMapping(path="/dashboard/user/validationCodeAuth", methods="PUT")
     */
    public function handle(): array
    {
        // 请求参数
        $params = $this->request->inputs(['phone', 'captcha']);

        // 类型验证
        $this->validated($params);

        // 模型数据
        $validationCode = $this->validationCode->getValidationCodeByPhoneCaptchaType($params['phone'], (int) $params['captcha'], 0, ['id', 'created_at']);

        if (! $validationCode) {
            throw new CommonException(ErrorCode::INVALID_PARAMS, '验证码错误');
        }

        if (time() - strtotime($validationCode['createdAt']) > 300) {
            throw new CommonException(ErrorCode::INVALID_PARAMS, '验证码已失效');
        }

        // 获取用户
        $userData = $this->user->getUserByPhone($params['phone'], ['id', 'status', 'password', 'tenant_id']);

        // 判断账户状态
        if ($userData['status'] != Status::NORMAL) {
            throw new CommonException(ErrorCode::ACCESS_REFUSE, sprintf('账户%s，无法登录', Status::getMessage($userData['status'])));
        }
        // 判断账户是否到期
        $tenant = $this->tenantService->getTenantById($userData['tenantId'], ['expired_at', 'status']);
        if ($tenant['status'] === 2) {
            throw new CommonException(ErrorCode::ACCESS_REFUSE, '您所属租户已禁用，请联系客服处理！');
        }
        if (! empty($tenant) && date('Y-m-d') > $tenant['expiredAt']) {
            throw new CommonException(ErrorCode::ACCESS_REFUSE, '无法登录，您的服务已到期，请联系客服处理！');
        }
        // 逻辑处理
        $guard = $this->auth->guard('jwt');
        /** @var JWTManager $jwt */
        $jwt = $guard->getJwtManager();

        // 更改验证码状态
        $this->validationCode->updateValidationCodeStatusById($validationCode['id'], 1);

        // 响应参数
        return [
            'token' => $guard->login($userData),
            'expire' => $jwt->getTtl(),
        ];
    }

    /**
     * 验证规则.
     */
    protected function rules(): array
    {
        return [
            'phone' => 'required|numeric',
            'captcha' => 'required|numeric',
        ];
    }

    /**
     * 属性替换.
     * @return array|string[] ...
     */
    protected function attributes(): array
    {
        return [
            'phone' => '手机号',
            'captcha' => '验证码',
        ];
    }
}
